﻿using System;
using System.Collections.Generic;
using System.Numerics;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.Normalization;

namespace ConAppCore.Test
{
    internal class TestNormalizer
    {
        public static void Test()
        {
            /****************************************************************
             * T[] 实现的接口
             * 
             * System.ICloneable
             * System.Collections.IList
             * System.Collections.ICollection
             * System.Collections.IEnumerable
             * System.Collections.IStructuralComparable
             * System.Collections.IStructuralEquatable
             * System.Collections.Generic.IList<T>
             * System.Collections.Generic.ICollection<T>
             * System.Collections.Generic.IEnumerable<T>
             * System.Collections.Generic.IReadOnlyList<T>
             * System.Collections.Generic.IReadOnlyCollection<T>
             * 
             ****************************************************************/


            //Test0();
            //Test01();

            //Test1_2();
            //Test1_3();

            //Test1();
            //Test2();
            //Test4();

            //Test5();
            //Test6();
            //Test7();

            TestSingleValue();
        }


        private static void TestSingleValue()
        {
            double min, max;

            min = 0;
            max = 100;
            PrimitiveTestSingleValue(min, max);

            min = 100;
            max = 500;
            PrimitiveTestSingleValue(min, max);

            min = -100;
            max = 0;
            PrimitiveTestSingleValue(min, max);

            min = -500;
            max = 100;
            PrimitiveTestSingleValue(min, max);

            min = -100;
            max = 100;
            PrimitiveTestSingleValue(min, max);

            min = -100;
            max = 500;
            PrimitiveTestSingleValue(min, max);

            min = -500;
            max = 100;
            PrimitiveTestSingleValue(min, max);
        }

        private static void PrimitiveTestSingleValue(double min, double max)
        {
            int len = 5;
            var destData = new float[len];
            var destData2 = new float[len];
            var destData3 = new float[len];
            double inputOffset, factor;

            var srcDataChar = new char[] { (char)0, (char)5, (char)10, (char)15, (char)20 };
            var normalizer11 = new Normalizer<char, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer12 = new Normalizer<char, float>(new NormalizerOptions(0, 20, false, min, max));
            new Normalizer<char, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataChar, destData3);

            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer11.Excute(srcDataChar[i], double.NaN, double.NaN);
            }
            var minMax1 = EnumerableEx.FindMinMaxIndex(srcDataChar);
            factor = normalizer12.CaculateNormalizeFactor(minMax1.MinValue.Value, minMax1.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer12.Excute(srcDataChar[i], factor, inputOffset);
            }

            var srcDataSbyte = new sbyte[] { -10, -5, 0, 5, 10 };
            var normalizer21 = new Normalizer<sbyte, float>(new NormalizerOptions(-10, 10, true, min, max));
            var normalizer22 = new Normalizer<sbyte, short>(new NormalizerOptions(-10, 10, true, min, max));
            new Normalizer<sbyte, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataSbyte, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer21.Excute(srcDataSbyte[i], double.NaN, double.NaN);
            }
            var minMax2 = EnumerableEx.FindMinMaxIndex(srcDataSbyte);
            factor = normalizer22.CaculateNormalizeFactor(minMax2.MinValue.Value, minMax2.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer22.Excute(srcDataSbyte[i], factor, inputOffset);
            }

            var srcDataSbyte2 = new sbyte[] { 0, 5, 10, 15, 20 };
            var normalizer31 = new Normalizer<sbyte, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer32 = new Normalizer<sbyte, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<sbyte, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataSbyte2, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer31.Excute(srcDataSbyte2[i], double.NaN, double.NaN);
            }
            var minMax3 = EnumerableEx.FindMinMaxIndex(srcDataSbyte2);
            factor = normalizer32.CaculateNormalizeFactor(minMax3.MinValue.Value, minMax3.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer32.Excute(srcDataSbyte2[i], factor, inputOffset);
            }

            var srcDataByte = new byte[] { 0, 5, 10, 15, 20 };
            var normalizer41 = new Normalizer<byte, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer42 = new Normalizer<byte, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<byte, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataByte, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer41.Excute(srcDataByte[i], double.NaN, double.NaN);
            }
            var minMax4 = EnumerableEx.FindMinMaxIndex(srcDataByte);
            factor = normalizer42.CaculateNormalizeFactor(minMax4.MinValue.Value, minMax4.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer42.Excute(srcDataByte[i], factor, inputOffset);
            }

            var srcDataShort = new short[] { -10, -5, 0, 5, 10 };
            var normalizer51 = new Normalizer<short, float>(new NormalizerOptions(-10, 10, true, min, max));
            var normalizer52 = new Normalizer<short, short>(new NormalizerOptions(-10, 10, true, min, max));
            new Normalizer<short, float>(new NormalizerOptions(-10, 10, false, min, max)).Excute(srcDataShort, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer51.Excute(srcDataShort[i], double.NaN, double.NaN);
            }
            var minMax5 = EnumerableEx.FindMinMaxIndex(srcDataShort);
            factor = normalizer52.CaculateNormalizeFactor(minMax5.MinValue.Value, minMax5.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer52.Excute(srcDataShort[i], factor, inputOffset);
            }

            var srcDataShort2 = new short[] { 0, 5, 10, 15, 20 };
            var normalizer61 = new Normalizer<short, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer62 = new Normalizer<short, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<short, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataShort2, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer61.Excute(srcDataShort2[i], double.NaN, double.NaN);
            }
            var minMax6 = EnumerableEx.FindMinMaxIndex(srcDataShort2);
            factor = normalizer62.CaculateNormalizeFactor(minMax6.MinValue.Value, minMax6.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer62.Excute(srcDataShort2[i], factor, inputOffset);
            }

            var srcDataUShort = new ushort[] { 0, 5, 10, 15, 20 };
            var normalizer71 = new Normalizer<ushort, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer72 = new Normalizer<ushort, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<ushort, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataUShort, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer71.Excute(srcDataUShort[i], double.NaN, double.NaN);
            }
            var minMax7 = EnumerableEx.FindMinMaxIndex(srcDataUShort);
            factor = normalizer72.CaculateNormalizeFactor(minMax7.MinValue.Value, minMax7.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer72.Excute(srcDataUShort[i], factor, inputOffset);
            }

            var srcDataInt = new int[] { -10, -5, 0, 5, 10 };
            var normalizer81 = new Normalizer<int, float>(new NormalizerOptions(-10, 10, true, min, max));
            var normalizer82 = new Normalizer<int, short>(new NormalizerOptions(-10, 10, true, min, max));
            new Normalizer<int, float>(new NormalizerOptions(-10, 10, false, min, max)).Excute(srcDataInt, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer81.Excute(srcDataInt[i], double.NaN, double.NaN);
            }
            var minMax8 = EnumerableEx.FindMinMaxIndex(srcDataInt);
            factor = normalizer82.CaculateNormalizeFactor(minMax8.MinValue.Value, minMax8.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer82.Excute(srcDataInt[i], factor, inputOffset);
            }

            var srcDataInt2 = new int[] { 0, 5, 10, 15, 20 };
            var normalizer91 = new Normalizer<int, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer92 = new Normalizer<int, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<int, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataInt2, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer91.Excute(srcDataInt2[i], double.NaN, double.NaN);
            }
            var minMax9 = EnumerableEx.FindMinMaxIndex(srcDataInt2);
            factor = normalizer92.CaculateNormalizeFactor(minMax9.MinValue.Value, minMax9.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer92.Excute(srcDataInt2[i], factor, inputOffset);
            }

            var srcDataUInt = new uint[] { 0, 5, 10, 15, 20 };
            var normalizer101 = new Normalizer<uint, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer102 = new Normalizer<uint, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<uint, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataUInt, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer101.Excute(srcDataUInt[i], double.NaN, double.NaN);
            }
            var minMax10 = EnumerableEx.FindMinMaxIndex(srcDataUInt);
            factor = normalizer102.CaculateNormalizeFactor(minMax10.MinValue.Value, minMax10.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer102.Excute(srcDataUInt[i], factor, inputOffset);
            }

            var srcDataLong = new long[] { -10, -5, 0, 5, 10 };
            var normalizer111 = new Normalizer<long, float>(new NormalizerOptions(-10, 10, true, min, max));
            var normalizer112 = new Normalizer<long, short>(new NormalizerOptions(-10, 10, true, min, max));
            new Normalizer<long, float>(new NormalizerOptions(-10, 10, false, min, max)).Excute(srcDataLong, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer111.Excute(srcDataLong[i], double.NaN, double.NaN);
            }
            var minMax11 = EnumerableEx.FindMinMaxIndex(srcDataLong);
            factor = normalizer112.CaculateNormalizeFactor(minMax11.MinValue.Value, minMax11.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer112.Excute(srcDataLong[i], factor, inputOffset);
            }

            var srcDataLong2 = new long[] { 0, 5, 10, 15, 20 };
            var normalizer121 = new Normalizer<long, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer122 = new Normalizer<long, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<long, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataLong2, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer121.Excute(srcDataLong2[i], double.NaN, double.NaN);
            }
            var minMax12 = EnumerableEx.FindMinMaxIndex(srcDataLong2);
            factor = normalizer122.CaculateNormalizeFactor(minMax12.MinValue.Value, minMax12.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer122.Excute(srcDataLong2[i], factor, inputOffset);
            }

            var srcDataULong = new ulong[] { 0, 5, 10, 15, 20 };
            var normalizer131 = new Normalizer<ulong, float>(new NormalizerOptions(0, 20, true, min, max));
            var normalizer132 = new Normalizer<ulong, short>(new NormalizerOptions(0, 20, true, min, max));
            new Normalizer<ulong, float>(new NormalizerOptions(0, 20, false, min, max)).Excute(srcDataULong, destData3);
            for (int i = 0; i < len; i++)
            {
                destData[i] = normalizer131.Excute(srcDataULong[i], double.NaN, double.NaN);
            }
            var minMax13 = EnumerableEx.FindMinMaxIndex(srcDataULong);
            factor = normalizer132.CaculateNormalizeFactor(minMax13.MinValue.Value, minMax13.MaxValue.Value, out inputOffset);
            for (int i = 0; i < len; i++)
            {
                destData2[i] = normalizer132.Excute(srcDataULong[i], factor, inputOffset);
            }
        }

        private static void Test7()
        {
            Span<short> srcData = new short[] { short.MinValue, -20000, -16384, -1000, -100, -10, 0, 10, 100, 1000, 16384, 20000, short.MaxValue };
            Span<float> destData = new float[srcData.Length];
            Span<float> destData2 = new float[srcData.Length];

            Demod_FM3();
            var normalizerfloat1 = new Normalizer<short, float>(new NormalizerOptions(short.MinValue, short.MaxValue, true, -1, 1) { Pre = 0.0000000001D });
            normalizerfloat1.Excute(srcData, destData);

            int index;
            for (int i = 0; i < srcData.Length; i++)
            {
                index = srcData[i] + 32768;
                destData2[i] = _lut16[index];
            }
        }


        private static float[] _lut16 = null;
        static void Demod_FM3()
        {
            _lut16 = new float[65536];
            const float scale16 = 1.0f / 32767.0f;
            for (var i = 0; i < 65536; i++)
            {
                _lut16[i] = (i - 32768) * scale16;
            }
        }

        private static void Test6()
        {
            double min, max;

            min = 0;
            max = 100;
            PrimitiveTest6(min, max);

            min = 100;
            max = 500;
            PrimitiveTest6(min, max);

            min = -100;
            max = 0;
            PrimitiveTest6(min, max);

            min = -500;
            max = 100;
            PrimitiveTest6(min, max);

            min = -100;
            max = 100;
            PrimitiveTest6(min, max);

            min = -100;
            max = 500;
            PrimitiveTest6(min, max);

            min = -500;
            max = 100;
            PrimitiveTest6(min, max);
        }
        private static void PrimitiveTest6(double min, double max)
        {
            int len = 5;
            var destData = new float[len];
            var destData2 = new short[len];


            var srcDataChar = new char[] { (char)0, (char)5, (char)10, (char)15, (char)20 };
            new Normalizer<char, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataChar, destData);
            new Normalizer<char, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataChar, destData2);

            var srcDataSbyte = new sbyte[] { -10, -5, 0, 5, 10 };
            new Normalizer<sbyte, float>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataSbyte, destData);
            new Normalizer<sbyte, short>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataSbyte, destData2);

            var srcDataSbyte2 = new sbyte[] { 0, 5, 10, 15, 20 };
            new Normalizer<sbyte, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataSbyte2, destData);
            new Normalizer<sbyte, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataSbyte2, destData2);

            var srcDataByte = new byte[] { 0, 5, 10, 15, 20 };
            new Normalizer<byte, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataByte, destData);
            new Normalizer<byte, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataByte, destData2);

            var srcDataShort = new short[] { -10, -5, 0, 5, 10 };
            new Normalizer<short, float>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataShort, destData);
            new Normalizer<short, short>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataShort, destData2);

            var srcDataShort2 = new short[] { 0, 5, 10, 15, 20 };
            new Normalizer<short, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataShort2, destData);
            new Normalizer<short, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataShort2, destData2);

            var srcDataUShort = new ushort[] { 0, 5, 10, 15, 20 };
            new Normalizer<ushort, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataUShort, destData);
            new Normalizer<ushort, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataUShort, destData2);

            var srcDataInt = new int[] { -10, -5, 0, 5, 10 };
            new Normalizer<int, float>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataInt, destData);
            new Normalizer<int, short>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataInt, destData2);

            var srcDataInt2 = new int[] { 0, 5, 10, 15, 20 };
            new Normalizer<int, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataInt2, destData);
            new Normalizer<int, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataInt2, destData2);

            var srcDataUInt = new uint[] { 0, 5, 10, 15, 20 };
            new Normalizer<uint, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataUInt, destData);
            new Normalizer<uint, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataUInt, destData2);

            var srcDataLong = new long[] { -10, -5, 0, 5, 10 };
            new Normalizer<long, float>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataLong, destData);
            new Normalizer<long, short>(new NormalizerOptions(-10, 10, true, min, max)).Excute(srcDataLong, destData2);

            var srcDataLong2 = new long[] { 0, 5, 10, 15, 20 };
            new Normalizer<long, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataLong2, destData);
            new Normalizer<long, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataLong2, destData2);

            var srcDataULong = new ulong[] { 0, 5, 10, 15, 20 };
            new Normalizer<ulong, float>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataULong, destData);
            new Normalizer<ulong, short>(new NormalizerOptions(0, 20, true, min, max)).Excute(srcDataULong, destData2);

        }


        private static void Test5()
        {
            long inputDataMin = -32767, inputDataMax = 32767;
            var srcData = new short[] { short.MinValue, -16384, -0, 16384, short.MaxValue };
            Span<float> destData = new float[srcData.Length];

            var normalizerfloat1 = new Normalizer<short, float>(new NormalizerOptions(inputDataMin, inputDataMax, true, -100, 100));
            normalizerfloat1.Excute(srcData, destData);

            var normalizerfloat2 = new Normalizer<short, float>(new NormalizerOptions(inputDataMin, inputDataMax, true, -100, 0));
            normalizerfloat2.Excute(srcData, destData);

            var normalizerfloat3 = new Normalizer<short, float>(new NormalizerOptions(inputDataMin, inputDataMax, true, -80, 20));
            normalizerfloat3.Excute(srcData, destData);

            var normalizerfloat4 = new Normalizer<short, float>(new NormalizerOptions(inputDataMin, inputDataMax, true, -20, 80));
            normalizerfloat4.Excute(srcData, destData);

            var normalizerfloat5 = new Normalizer<short, float>(new NormalizerOptions(inputDataMin, inputDataMax, true, 0, 100));
            normalizerfloat5.Excute(srcData, destData);

        }



        private static void Test4()
        {
            Span<double> srcData = new double[]
           {
               0,5.9,-5.9
                //0,5.986317836804702E-07,-4.443377670545247E-08,-7.306472247654016E-07,-1.3131397045771467E-06,
                //-1.7737453579045752E-06,-2.006400075510157E-06,-1.7272963619597622E-06,-1.173641513600301E-06,-5.414460564936203E-07,
                //1.907688547752267E-07,8.124418801630436E-07,1.1565834026045111E-06,1.192609186665303E-06,1.0103611940305429E-06,
                //5.104302705846763E-07,-2.6083925046341615E-07,-9.484300229535043E-07,-1.49069771334929E-06,-1.8094817972648815E-06,
                // -1.7984566881922568E-06, -1.3851594326290538E-06, -7.164512983062173E-07, -9.950325139920104E-08, 5.648278629366888E-07,
                // 1.0960509131347594E-06, 1.274781297147465E-06, 1.1911440357386414E-06, 8.481130873860575E-07, 2.1460209900712913E-07
           };

            //srcData = new double[] { -1, -0.5f, 0, 0.5f, 1 };
            var normalizer = new Normalizer<double, short>(new NormalizerOptions(short.MinValue, short.MaxValue) { Pre = 0.000000001d, SlidFrames = 1000 });
            Span<short> destData = new short[srcData.Length];
            normalizer.Excute(srcData, destData);
        }




        private static void Test2()
        {
            double min, max;

            min = 0;
            max = 100;
            PrimitiveTest2(min, max);

            min = 100;
            max = 500;
            PrimitiveTest2(min, max);

            min = -100;
            max = 0;
            PrimitiveTest2(min, max);

            min = -500;
            max = 100;
            PrimitiveTest2(min, max);

            min = -100;
            max = 100;
            PrimitiveTest2(min, max);

            min = -100;
            max = 500;
            PrimitiveTest2(min, max);

            min = -500;
            max = 100;
            PrimitiveTest2(min, max);
        }
        private static void PrimitiveTest2(double min, double max)
        {
            int len = 5;
            float[] destData = new float[len];
            short[] destData2 = new short[len];

            var srcDataChar = new char[] { (char)0, (char)5, (char)10, (char)15, (char)20 };
            var normalizerChar1 = new Normalizer<char, float>(new NormalizerOptions(min, max));
            var normalizerChar2 = new Normalizer<char, short>(new NormalizerOptions(min, max));
            normalizerChar1.Excute(srcDataChar, destData);
            normalizerChar2.Excute(srcDataChar, destData2);

            var srcDataSbyte = new sbyte[] { -10, -5, 0, 5, 10 };
            var normalizerSbyte1 = new Normalizer<sbyte, float>(new NormalizerOptions(min, max));
            var normalizerSbyte2 = new Normalizer<sbyte, short>(new NormalizerOptions(min, max));
            normalizerSbyte1.Excute(srcDataSbyte, destData);
            normalizerSbyte2.Excute(srcDataSbyte, destData2);

            var srcDataSbyte2 = new sbyte[] { 0, 5, 10, 15, 20 };
            var normalizerSbyte12 = new Normalizer<sbyte, float>(new NormalizerOptions(min, max));
            var normalizerSbyte22 = new Normalizer<sbyte, short>(new NormalizerOptions(min, max));
            normalizerSbyte12.Excute(srcDataSbyte2, destData);
            normalizerSbyte22.Excute(srcDataSbyte2, destData2);

            var srcDataByte = new byte[] { 0, 5, 10, 15, 20 };
            var normalizerByte1 = new Normalizer<byte, float>(new NormalizerOptions(min, max));
            var normalizerByte2 = new Normalizer<byte, short>(new NormalizerOptions(min, max));
            normalizerByte1.Excute(srcDataByte, destData);
            normalizerByte2.Excute(srcDataByte, destData2);

            var srcDataShort = new short[] { -10, -5, 0, 5, 10 };
            var normalizerShort1 = new Normalizer<short, float>(new NormalizerOptions(min, max));
            var normalizerShort2 = new Normalizer<short, short>(new NormalizerOptions(min, max));
            normalizerShort1.Excute(srcDataShort, destData);
            normalizerShort2.Excute(srcDataShort, destData2);

            var srcDataShort2 = new short[] { 0, 5, 10, 15, 20 };
            var normalizerShort12 = new Normalizer<short, float>(new NormalizerOptions(min, max));
            var normalizerShort22 = new Normalizer<short, short>(new NormalizerOptions(min, max));
            normalizerShort12.Excute(srcDataShort2, destData);
            normalizerShort22.Excute(srcDataShort2, destData2);

            var srcDataUShort = new ushort[] { 0, 5, 10, 15, 20 };
            var normalizerUShort1 = new Normalizer<ushort, float>(new NormalizerOptions(min, max));
            var normalizerUShort2 = new Normalizer<ushort, short>(new NormalizerOptions(min, max));
            normalizerUShort1.Excute(srcDataUShort, destData);
            normalizerUShort2.Excute(srcDataUShort, destData2);

            var srcDataInt = new int[] { -10, -5, 0, 5, 10 };
            var normalizerInt1 = new Normalizer<int, float>(new NormalizerOptions(min, max));
            var normalizerInt2 = new Normalizer<int, short>(new NormalizerOptions(min, max));
            normalizerInt1.Excute(srcDataInt, destData);
            normalizerInt2.Excute(srcDataInt, destData2);

            var srcDataInt2 = new int[] { 0, 5, 10, 15, 20 };
            var normalizerInt12 = new Normalizer<int, float>(new NormalizerOptions(min, max));
            var normalizerInt22 = new Normalizer<int, short>(new NormalizerOptions(min, max));
            normalizerInt12.Excute(srcDataInt2, destData);
            normalizerInt22.Excute(srcDataInt2, destData2);

            var srcDataUInt = new uint[] { 0, 5, 10, 15, 20 };
            var normalizerUInt1 = new Normalizer<uint, float>(new NormalizerOptions(min, max));
            var normalizerUInt2 = new Normalizer<uint, short>(new NormalizerOptions(min, max));
            normalizerUInt1.Excute(srcDataUInt, destData);
            normalizerUInt2.Excute(srcDataUInt, destData2);

            var srcDataLong = new long[] { -10, -5, 0, 5, 10 };
            var normalizerLong1 = new Normalizer<long, float>(new NormalizerOptions(min, max));
            var normalizerLong2 = new Normalizer<long, short>(new NormalizerOptions(min, max));
            normalizerLong1.Excute(srcDataLong, destData);
            normalizerLong2.Excute(srcDataLong, destData2);

            var srcDataLong2 = new long[] { 0, 5, 10, 15, 20 };
            var normalizerLong12 = new Normalizer<long, float>(new NormalizerOptions(min, max));
            var normalizerLong22 = new Normalizer<long, short>(new NormalizerOptions(min, max));
            normalizerLong12.Excute(srcDataLong2, destData);
            normalizerLong22.Excute(srcDataLong2, destData2);

            var srcDataULong = new ulong[] { 0, 5, 10, 15, 20 };
            var normalizerULong1 = new Normalizer<ulong, float>(new NormalizerOptions(min, max));
            var normalizerULong2 = new Normalizer<ulong, short>(new NormalizerOptions(min, max));
            normalizerULong1.Excute(srcDataULong, destData);
            normalizerULong2.Excute(srcDataULong, destData2);

            var srcDataFloat = new float[] { -10, -5, 0, 5, 10 };
            var normalizerFloat1 = new Normalizer<float, float>(new NormalizerOptions(min, max));
            var normalizerFloat2 = new Normalizer<float, short>(new NormalizerOptions(min, max));
            normalizerFloat1.Excute(srcDataFloat, destData);
            normalizerFloat2.Excute(srcDataFloat, destData2);

            var srcDataFloat2 = new float[] { 0, 5, 10, 15, 20 };
            var normalizerFloat12 = new Normalizer<float, float>(new NormalizerOptions(min, max));
            var normalizerFloat22 = new Normalizer<float, short>(new NormalizerOptions(min, max));
            normalizerFloat12.Excute(srcDataFloat2, destData);
            normalizerFloat22.Excute(srcDataFloat2, destData2);

            var srcDataDouble = new double[] { -10, -5, 0, 5, 10 };
            var normalizerDouble1 = new Normalizer<double, float>(new NormalizerOptions(min, max));
            var normalizerDouble2 = new Normalizer<double, short>(new NormalizerOptions(min, max));
            normalizerDouble1.Excute(srcDataDouble, destData);
            normalizerDouble2.Excute(srcDataDouble, destData2);

            var srcDataDouble2 = new double[] { 0, 5, 10, 15, 20 };
            var normalizerDouble12 = new Normalizer<double, float>(new NormalizerOptions(min, max));
            var normalizerDouble22 = new Normalizer<double, short>(new NormalizerOptions(min, max));
            normalizerDouble12.Excute(srcDataDouble2, destData);
            normalizerDouble22.Excute(srcDataDouble2, destData2);
        }



        private static void Test1_3()
        {
            int len = 5;
            float[] destData = new float[len];

            var srcDataShort = new short[] { -10, -5, 0, 5, 10 };
            var normalizerShort1 = new Normalizer<short, float>(new NormalizerOptions(-100, 100));
            normalizerShort1.Excute(srcDataShort, destData);


            var srcDataShort2 = new short[] { -100, -50, 0, 50, 100 };
            var normalizerShort12 = new Normalizer<short, float>(new NormalizerOptions(-10, 10));
            normalizerShort12.Excute(srcDataShort2, destData);

            var srcDataShort3 = new short[] { 0, 5, 10, 15, 20 };
            var normalizerShort13 = new Normalizer<short, float>(new NormalizerOptions(-100, 100));
            normalizerShort13.Excute(srcDataShort3, destData);

            var srcDataShort4 = new short[] { 0, 50, 100, 150, 200 };
            var normalizerShort14 = new Normalizer<short, float>(new NormalizerOptions(-10, 10));
            normalizerShort14.Excute(srcDataShort4, destData);
        }

        private static void Test1_2()
        {
            const int len = 5;
            Span<float> srcData;
            Span<short> destData = new short[len];

            var normalizer1 = new Normalizer<float, short>(new NormalizerOptions(-100, 100));
            var normalizer2 = new Normalizer<float, short>(new NormalizerOptions(-100, 0));
            var normalizer3 = new Normalizer<float, short>(new NormalizerOptions(0, 100));
            var normalizer4 = new Normalizer<float, short>(new NormalizerOptions(-100, 20));
            var normalizer5 = new Normalizer<float, short>(new NormalizerOptions(-20, 100));

            for (int i = 0; i < 5; i++)
            {
                switch (i)
                {
                    case 0:
                        srcData = new float[len] { -1, -0.5f, 0, 0.5f, 1 };
                        break;
                    case 1:
                        srcData = new float[len] { -10, -5, 0, 5, 10 };
                        break;
                    case 2:
                        srcData = new float[len] { 0, 5, 10, 15, 20 };
                        break;
                    case 3:
                        srcData = new float[len] { -20, -15, -10, -5, 0 };
                        break;
                    default:
                        return;
                }

                normalizer1.Excute(srcData, destData);
                normalizer2.Excute(srcData, destData);
                normalizer3.Excute(srcData, destData);
                normalizer4.Excute(srcData, destData);
                normalizer5.Excute(srcData, destData);
            }

        }

        private static void Test1()
        {
            var srcData = new float[] {
            0.00571947126f  ,            0.0655468553f  ,            0.00127611554f  ,            -0.06728029f  ,            -0.125217408f  ,
            //-0.170726433f  ,            -0.193577126f  ,            -0.166152522f  ,            -0.111375444f  ,            -0.0483986847f   ,
            //0.0247952f   ,            0.08687431f  ,            0.121120133f ,            0.124697879f ,            0.1065838f   ,
            //0.0567403361f    ,            -0.0203615054f   ,            -0.08898141f     ,            -0.142798826f    ,            -0.1742429f      ,
            //-0.173158258f    ,            -0.132353991f    ,            -0.0658643544f   ,            -0.00423067575f  ,            0.06217221f  ,
            //0.115105242f ,            0.132852614f ,            0.124552406f ,            0.09042914f  ,            0.0271780323f     
            };

            srcData = new float[] { -1, -0.5f, 0, 0.5f, 1 };
            float[] destData = new float[srcData.Length];
            short[] destData2 = new short[srcData.Length];

            var normalizerfloat = new Normalizer<float, float>(new NormalizerOptions(-100, 0));
            var normalizerShort = new Normalizer<float, short>(new NormalizerOptions(-100, 0));
            normalizerfloat.Excute(srcData, destData);
            normalizerShort.Excute(srcData, destData2);

            var normalizerfloat2 = new Normalizer<float, float>(new NormalizerOptions(0, 255));
            var normalizerShort2 = new Normalizer<float, short>(new NormalizerOptions(0, 255));
            normalizerfloat2.Excute(srcData, destData);
            normalizerShort2.Excute(srcData, destData2);

            var normalizerfloat3 = new Normalizer<float, float>(new NormalizerOptions(-100, 100));
            var normalizerShort3 = new Normalizer<float, short>(new NormalizerOptions(-100, 100));
            normalizerfloat3.Excute(srcData, destData);
            normalizerShort3.Excute(srcData, destData2);


            var normalizerfloat4 = new Normalizer<float, float>(new NormalizerOptions(-20, 100));
            var normalizerShort4 = new Normalizer<float, short>(new NormalizerOptions(-20, 100));
            normalizerfloat4.Excute(srcData, destData);
            normalizerShort4.Excute(srcData, destData2);

            var normalizerfloat5 = new Normalizer<float, float>(new NormalizerOptions(-100, 20));
            var normalizerShort5 = new Normalizer<float, short>(new NormalizerOptions(-100, 20));
            normalizerfloat5.Excute(srcData, destData);
            normalizerShort5.Excute(srcData, destData2);

            var normalizerfloat6 = new Normalizer<float, float>(new NormalizerOptions(-255, 0));
            var normalizerShort6 = new Normalizer<float, short>(new NormalizerOptions(-255, 0));
            normalizerfloat6.Excute(srcData, destData);
            normalizerShort6.Excute(srcData, destData2);

        }
        //static abstract bool IsInteger(TSelf value);




        private static void Test01()
        {
            Span<short> source = new short[] { 0, 5, 10, 15, 20 };
            Span<short> dest = new short[source.Length];
            Span<double> dest2 = new double[source.Length];

            new Normalizer<short, short>(new NormalizerOptions(0, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(0, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, 0, 100);

            new Normalizer<short, short>(new NormalizerOptions(-100, 0)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 0)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 0);

            new Normalizer<short, short>(new NormalizerOptions(-100, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 100);

            new Normalizer<short, short>(new NormalizerOptions(-100, 20)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 20)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 20);

            new Normalizer<short, short>(new NormalizerOptions(-20, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-20, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -20, 100);


            source = new short[] { -10, -5, 0, 5, 10 };
            new Normalizer<short, short>(new NormalizerOptions(0, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(0, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, 0, 100);

            new Normalizer<short, short>(new NormalizerOptions(-100, 0)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 0)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 0);

            new Normalizer<short, short>(new NormalizerOptions(-100, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 100);

            new Normalizer<short, short>(new NormalizerOptions(-100, 20)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-100, 20)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -100, 20);

            new Normalizer<short, short>(new NormalizerOptions(-20, 100)).Excute(source, dest);
            new Normalizer<short, double>(new NormalizerOptions(-20, 100)).Excute(source, dest2);
            PrimitiveTest01(source, dest, -20, 100);
        }

        private static void PrimitiveTest01(Span<short> source, Span<short> dest, double destMin, double destMax)
        {
            var minMax = EnumerableEx.FindMinMaxIndex(source);
            double inputOffset = (double)(minMax.MinValue.Value + minMax.MaxValue.Value) / 2;
            double outputOffset = (destMin + destMax) / 2;
            double temp;
            for (int i = 0; i < source.Length; i++)
            {
                temp = (source[i] - inputOffset) * (destMax - destMin) / (minMax.MaxValue.Value - minMax.MinValue.Value) + outputOffset;

                if (temp < destMin)
                {
                    temp = destMin;
                }
                else if (temp > destMax)
                {
                    temp = destMax;
                }
                dest[i] = (short)temp;
            }
        }



        private static void Test0()
        {
            float[] srcData = new float[] { -1, -0.5f, 0, 0.5f, 1 };
            short[] ret = new short[srcData.Length];
            Test0(srcData, ret, 0, 255);

            Test0(srcData, ret, -100, 100);

            Test0(srcData, ret, -255, 0);

            Test0(srcData, ret, -100, 20);

            Test0(srcData, ret, -20, 100);
        }

        private static void Test0(float[] source, short[] ret, double min, double max)
        {
            double offset = (min + max) / 2;//(A4+B4)/2
            //var d4 = Math.Max(Math.Abs(min), Math.Abs(max)) - Math.Abs(offset);//MAX(ABS(A4),ABS(B4))-ABS(C4)

            var valueRange = EnumerableEx.FindMinMaxIndex(source);
            var dataAbsMax = Math.Max(Math.Abs(valueRange.MinValue.Value), Math.Abs(valueRange.MaxValue.Value));
            var factor = (Math.Max(Math.Abs(min), Math.Abs(max)) - Math.Abs(offset)) / dataAbsMax;

            double temp;
            for (int i = 0; i < source.Length; i++)
            {
                //ROUND($D$4/1*A12+$C$4,0)
                temp = factor * source[i] + offset;
                //temp = d4 / dataAbsMax * srcData[i] + offset;
                if (temp < min)
                {
                    temp = min;
                }
                else if (temp > max)
                {
                    temp = max;
                }
                else
                {

                }
                ret[i] = (short)temp;
            }

        }

    }


    //public struct X :
    //    IComparable,
    //    IComparable<Single>,
    //    IConvertible,
    //    IEquatable<Single>,
    //    IFormattable,
    //    IParsable<Single>,
    //    ISpanFormattable,
    //    ISpanParsable<Single>,
    //    IAdditionOperators<Single, Single, Single>,+
    //    IAdditiveIdentity<Single, Single>,
    //    IBinaryFloatingPointIeee754<Single>,
    //    IBinaryNumber<Single>,
    //    IBitwiseOperators<Single, Single, Single>, & | ~ ^
    //    IComparisonOperators<Single, Single, bool>,> < >= <=
    //    IEqualityOperators<Single, Single, bool>,== !=
    //    IDecrementOperators<Single>,--
    //    IDivisionOperators<Single, Single, Single>, /
    //    IIncrementOperators<Single>, ++
    //    IModulusOperators<Single, Single, Single>,%
    //    IMultiplicativeIdentity<Single, Single>,

    //    IMultiplyOperators<Single, Single, Single>,*

    //    INumber<Single>, Min Max

    //    INumberBase<Single>, Abs
    //    ISubtractionOperators<Single, Single, Single>,-
    //    IUnaryNegationOperators<Single, Single>,-
    //    IUnaryPlusOperators<Single, Single>,+

    //    IUtf8SpanFormattable,
    //    IUtf8SpanParsable<Single>,
    //    IExponentialFunctions<Single>,
    //    IFloatingPointConstants<Single>,
    //    IFloatingPoint<Single>,
    //    ISignedNumber<Single>,
    //    IFloatingPointIeee754<Single>,
    //    IHyperbolicFunctions<Single>,
    //    ILogarithmicFunctions<Single>, Log
    //    IPowerFunctions<Single>, Pow
    //    IRootFunctions<Single>, Sqrt
    //    ITrigonometricFunctions<Single>, 三角函数
    //    IMinMaxValue<Single>
    //{

    //}


    public interface IMinMaxValue22<TSelf> where TSelf : IMinMaxValue22<TSelf>
    {
        //
        // 摘要:
        //     Gets the maximum value of the current type.
        static abstract TSelf MaxValue { get; }
        //
        // 摘要:
        //     Gets the minimum value of the current type.
        static abstract TSelf MinValue { get; }
    }

    public class YFNum : IMinMaxValue22<YFNum>
    {
        public static YFNum MaxValue => throw new NotImplementedException();

        public static YFNum MinValue => throw new NotImplementedException();
    }
}
